import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.preprocessing import StandardScaler

# 创建数据框
data = {
    '债券简称': ['G21苏林1', 'G21综能1', 'G21华新1', 'G21华新2', '21北电', 'PR文1A1', 'PR文1A2',
                 'PR文1B', 'GC华能04', 'GC太科01', '21昆明轨道', 'G苏天2优', 'G苏天2次'],
    '计划发行规模（亿）': [2.0000, 10.0000, 10.0000, 10.0000, 5.0000, 2.5200, 2.8000,
                         0.9800, 20.0000, 1.0000, 10.0000, 10.1200, 0.5300],
    '发行金额上限（亿）': [2.0000, 10.0000, 10.0000, 10.0000, np.nan, np.nan, np.nan,
                         np.nan, 20.0000, 1.0000, 15.0000, np.nan, np.nan],
    '债券评级': [np.nan, 'AA+', 'AAA', 'AAA', np.nan, 'AAA', 'AAA', 'AA+', 'AAA', 'AA', 'AAA', 'AAA', np.nan]
}

df = pd.DataFrame(data)

# 设置全局字体
plt.rcParams['font.sans-serif'] = ['SimHei']    # SimHei 字体就是黑体
plt.rcParams['axes.unicode_minus'] = False     #解决保存图像是负号'-'显示为方块的问题

# 判断是否存在缺失值
has_missing_values = df.isnull().values.any()
print("是否存在缺失值：", has_missing_values)

# 处理缺失值
df.fillna(value={'发行金额上限（亿）': 0, '债券评级': '未评级'}, inplace=True)

# 数据特征分析
print("数据特征分析：")
print(df.describe())

# 数据异常值处理和箱线图
plt.figure(figsize=(8, 6))
sns.boxplot(data=df[['计划发行规模（亿）', '发行金额上限（亿）']])
plt.title("数据异常值处理 - 箱线图")
plt.show()

# 标准化处理
scaler = StandardScaler()
scaled_data = scaler.fit_transform(df[['计划发行规模（亿）', '发行金额上限（亿）']])
scaled_df = pd.DataFrame(scaled_data, columns=['计划发行规模（亿）', '发行金额上限（亿）'])
print("标准化处理后的数据：")
print(scaled_df)

from sklearn.cluster import KMeans, DBSCAN
from sklearn.mixture import GaussianMixture
from sklearn import metrics

# K-means 聚类建模
kmeans_model = KMeans(n_clusters=3, random_state=0)
df['K-means 聚类标签'] = kmeans_model.fit_predict(scaled_df)

# DBSCAN 聚类建模
dbscan_model = DBSCAN(eps=0.5, min_samples=3)
df['DBSCAN 聚类标签'] = dbscan_model.fit_predict(scaled_df)

# GMM 聚类建模
gmm_model = GaussianMixture(n_components=3, random_state=0)
df['GMM 聚类标签'] = gmm_model.fit_predict(scaled_df)

# 聚类评估
kmeans_silhouette = metrics.silhouette_score(scaled_df, df['K-means 聚类标签'])
dbscan_silhouette = metrics.silhouette_score(scaled_df, df['DBSCAN 聚类标签'])
gmm_silhouette = metrics.silhouette_score(scaled_df, df['GMM 聚类标签'])

# 可视化展示
# 绘制K-means 聚类结果
plt.figure(figsize=(8, 6))
plt.scatter(scaled_df['计划发行规模（亿）'], scaled_df['发行金额上限（亿）'], c=df['K-means 聚类标签'], cmap='viridis')
plt.title('K-means 聚类结果')
plt.xlabel('计划发行规模（亿）')
plt.ylabel('发行金额上限（亿）')
plt.show()

# 绘制DBSCAN 聚类结果
plt.figure(figsize=(8, 6))
plt.scatter(scaled_df['计划发行规模（亿）'], scaled_df['发行金额上限（亿）'], c=df['DBSCAN 聚类标签'], cmap='viridis')
plt.title('DBSCAN 聚类结果')
plt.xlabel('计划发行规模（亿）')
plt.ylabel('发行金额上限（亿）')
plt.show()

# 绘制GMM 聚类结果
plt.figure(figsize=(8, 6))
plt.scatter(scaled_df['计划发行规模（亿）'], scaled_df['发行金额上限（亿）'], c=df['GMM 聚类标签'], cmap='viridis')
plt.title('GMM 聚类结果')
plt.xlabel('计划发行规模（亿）')
plt.ylabel('发行金额上限（亿）')
plt.show()

# 比较聚类算法的轮廓系数和Calinski-Harabasz指数
kmeans_calinski_harabasz = metrics.calinski_harabasz_score(scaled_df, df['K-means 聚类标签'])
dbscan_calinski_harabasz = metrics.calinski_harabasz_score(scaled_df, df['DBSCAN 聚类标签'])
gmm_calinski_harabasz = metrics.calinski_harabasz_score(scaled_df, df['GMM 聚类标签'])

# 可视化展示聚类指标
labels = ['K-means', 'DBSCAN', 'GMM']
silhouette_scores = [kmeans_silhouette, dbscan_silhouette, gmm_silhouette]
calinski_harabasz_scores = [kmeans_calinski_harabasz, dbscan_calinski_harabasz, gmm_calinski_harabasz]

x = np.arange(len(labels))
width = 0.35

fig, ax = plt.subplots(figsize=(10, 6))
bar1 = ax.bar(x - width/2, silhouette_scores, width, label='Silhouette Score')
bar2 = ax.bar(x + width/2, calinski_harabasz_scores, width, label='Calinski-Harabasz Score')

ax.set_ylabel('Scores')
ax.set_title('聚类算法评估指标')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()

plt.show()

# 输出聚类评估结果
print("K-means 聚类轮廓系数：", kmeans_silhouette, "，Calinski-Harabasz指数：", kmeans_calinski_harabasz)
print("DBSCAN 聚类轮廓系数：", dbscan_silhouette, "，Calinski-Harabasz指数：", dbscan_calinski_harabasz)
print("GMM 聚类轮廓系数：", gmm_silhouette, "，Calinski-Harabasz指数：", gmm_calinski_harabasz)
